<template>
  <div class="book-chapter">
    <Card>
      <div slot="title">
        <p class="title">
          {{ bookInfo.name }}&nbsp;❘&nbsp;章节管理
          <!-- <Button class="add-icon" icon="ios-cloud-download-outline" @click="downloadExample">下载导入模板</Button> -->
          <Button class="add-icon" icon="md-arrow-down" @click="downloadChapter">
            下载全部章节
          </Button>
          <Upload
            class="upload-btn"
            :action="uploadUrl"
            :show-upload-list="false"
            :on-success="handleSuccess"
            :on-error="handleError"
            :on-format-error="handleFormatError"
            :headers="uploadHeader"
            :before-upload="handleBeforeUpload"
            accept="application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, text/plain"
          >
            <Button type="primary" icon="ios-cloud-upload-outline">
              导入章节
            </Button>
          </Upload>
          <input
            type="file"
            id="upload"
            name="upload"
            style="display: none"
            accept="text/plain"
            @change="fileHandler"
          />
          <label for="upload" class="upload-label ivu-btn ivu-btn-primary">
            <Icon type="android-add" style="margin-right: 4px"></Icon>将txt转换成csv
          </label>
          <Button
            class="add-icon"
            type="primary"
            icon="android-add"
            @click="handleAdd"
          >
            新增章节
          </Button>
        </p>
      </div>

      <Table :columns="columnsList" :data="chapters" :loading="loading"></Table>
      <Page
        class="pager"
        v-if="total > 0"
        :current="page"
        :total="total"
        show-total
        show-elevator
        show-sizer
        :page-size="limit"
        @on-change="handlePageChange"
        @on-page-size-change="handleSizeChange"
      ></Page>
    </Card>
    <Modal
      class="chapter-dialog"
      v-model="isShowModal"
      :title="modalTitle"
      :loading="modalLoading"
      @on-ok="handleModalConfrim"
      @on-cancel="handleModalCancel"
      width="600"
      :mask-closable="false"
    >
      <Form
        ref="modalForm"
        :model="modalData"
        :rules="modalRule"
        :label-width="100"
      >
        <FormItem prop="num" label="章节序号" :error="modalError.num">
          <i-input
            v-model="modalData.num"
            placeholder="请输入章节序号"
          ></i-input>
        </FormItem>
        <FormItem prop="name" label="章节标题" :error="modalError.name">
          <i-input
            v-model="modalData.name"
            placeholder="请输入章节标题"
          ></i-input>
        </FormItem>
        <FormItem prop="content" label="章节内容" :error="modalError.content">
          <i-input
            class="small-font"
            v-model="modalData.content"
            type="textarea"
            :autosize="{ minRows: 8, maxRows: 15 }"
            placeholder="请输入章节内容"
            style="font-size: 12px"
          ></i-input>
        </FormItem>
      </Form>
    </Modal>
    <Modal
      title="上传提示"
      v-model="showUploadingModal"
      width="800"
      :closable="false"
      :mask-closable="false"
      @on-cancel="closeUploadModal"
      @on-ok="handleUploadModalConfrim"
    >
      <Steps :current="currentStep">
        <Step :title="step[0].title" :content="step[0].content"></Step>
        <Step :title="step[1].title" :content="step[1].content"></Step>
        <Step :title="step[2].title" :content="step[2].content"></Step>
        <Step :title="step[3].title" :content="step[3].content"></Step>
      </Steps>
      <template v-if="currentStep === 2">
        <p style="padding: 10px">分析得到的错误章节如下:</p>
        <template v-if="errorChapters.length > 0">
          <Table
            ref="uploadTable"
            :columns="inlineColumn"
            :data="curChapters"
          />
          <Page
            class="pager"
            style="padding: 10px"
            :page-size="5"
            :current="uploadPage"
            :total="errorChapters.length"
            show-total
            show-elevator
            @on-change="handleUploadPageChange"
          ></Page>
        </template>
        <template v-else>
          <p style="text-align: center; padding: 10px 0">未分析出错误</p>
        </template>
      </template>
    </Modal>
  </div>
</template>

<script>
import { oldHttp, baseURL } from "@/utils/http";
import Cookies from "js-cookie";
import chinese2num from "@/utils/chinese2num";
import ExportJsonExcel from "js-export-excel";

export default {
  data() {
    return {
      uploadUrl: "",
      uploadHeader: {},
      loading: false,
      chapters: [],
      bookInfo: {},
      total: 0,
      page: 1,
      limit: 10,
      isShowModal: false, // 控制modal的显隐
      modalLoading: true, // 点击modal确定按钮是否显示loading
      modalTitle: "", // modal标题
      isAddOrUpdateModal: "", // 是新增弹窗或者更新弹窗
      currentChapterId: "", // 当前正在修改的书籍Id
      modalData: {
        num: "",
        name: "",
        content: "",
      },
      modalRule: {
        num: [{ required: true, message: "请输入章节序号", trigger: "blur" }],
        name: [{ required: true, message: "请输入章节标题", trigger: "blur" }],
        content: [
          { required: true, message: "请输入章节内容", trigger: "blur" },
        ],
      },
      modalError: {
        num: "",
        name: "",
        content: "",
      }, // modal错误提示信息
      showUploadingModal: false, // 是否展示上传中的进度条
      currentStep: 0, // 上传章节的当前步骤数
      step: [
        { title: "读取本地文件", content: "读取中.." },
        { title: "解析书籍章节", content: "未开始.." },
        { title: "确认章节", content: "未开始..", ellipsis: true },
        { title: "导出csv文件", content: "未开始.." },
      ],
      columnsList: [
        {
          title: "序号",
          width: 80,
          key: "index",
          align: "center",
        },
        {
          title: "章节ID",
          align: "center",
          key: "_id",
          ellipsis: true,
        },
        {
          title: "章节标题",
          align: "center",
          key: "name",
        },
        {
          title: "章节序号",
          align: "center",
          key: "num",
          render: (h, params) => {
            return h("span", "第" + params.row.num + "章");
          },
        },
        {
          title: "章节内容",
          align: "center",
          key: "content",
          ellipsis: true,
        },
        {
          title: "操作",
          align: "center",
          width: 190,
          key: "handle",
          render: (h, params) => {
            return h("div", [
              h(
                "Button",
                {
                  class: "change-btn",
                  props: {
                    type: "primary",
                  },
                  on: {
                    click: () => {
                      // 打开修改弹窗
                      this.modalData = {
                        num: params.row.num.toString(),
                        name: params.row.name,
                        content: params.row.content,
                      };
                      this.isShowModal = true;
                      this.modalTitle = "修改章节";
                      this.isAddOrUpdateModal = "update";
                      this.currentChapterId = params.row._id;
                    },
                  },
                },
                "修改"
              ),
              h(
                "Button",
                {
                  props: {
                    type: "error",
                  },
                  on: {
                    click: () => {
                      this.$Modal.confirm({
                        title: "温馨提示",
                        content: "确定要删除此章节？",
                        onOk: () => {
                          oldHttp
                            .delete(
                              "/api/admin/chapter/" + params.row._id,
                              {},
                              "删除章节"
                            )
                            .then((res) => {
                              if (res.ok) {
                                // 更新tableData
                                this.isShowModal = false;
                                this.$Message.success("删除章节成功");
                                this.getChapters();
                              }
                            });
                        },
                        onCancel: () => {},
                      });
                    },
                  },
                },
                "删除"
              ),
            ]);
          },
        },
      ],
      inlineColumn: [
        { title: "序号", key: "num", width: 100 },
        { title: "章节名称", key: "name", width: 120 },
        { title: "章节内容", key: "content", ellipsis: true },
        { title: "提示", key: "error" },
      ],
      uploadChapters: [], // 分析章节得到的数据
      curChapters: [],
      errorChapters: [],
      uploadPage: 1,
    };
  },
  methods: {
    // get chapters of this book
    getChapters() {
      let self = this;
      self.loading = true;
      oldHttp
        .get(
          "/api/admin/book/" + self.$route.params.bookid + "/chapter",
          { page: self.page, limit: self.limit },
          "获取章节列表",
          20000
        )
        .then((res) => {
          if (res.ok) {
            self.bookInfo = res.bookInfo;
            self.chapters = res.lists.map((item, index) => {
              item.index = (self.page - 1) * self.limit + index + 1;
              return item;
            });
            self.total = res.total;
          }
          self.loading = false;
        });
    },
    handleAdd() {
      this.modalData = {
        num: "",
        name: "",
        content: "",
      };
      this.isShowModal = true;
      this.modalTitle = "新增书籍";
      this.isAddOrUpdateModal = "add";
    },
    handleModalConfrim() {
      let self = this;
      // 合法性校验
      self.$refs["modalForm"].validate((valid) => {
        if (valid) {
          let intergeRegExp = /^\d+$/;
          if (intergeRegExp.test(self.modalData.num)) {
            let data = JSON.parse(JSON.stringify(self.modalData));
            data.num = parseInt(data.num);
            if (self.isAddOrUpdateModal === "add") {
              oldHttp
                .post(
                  "/api/admin/book/" + self.$route.params.bookid + "/chapter",
                  data,
                  "新增章节"
                )
                .then((res) => {
                  self.modalLoading = false;
                  // 避免校验完直接关闭弹窗
                  self.$nextTick(() => {
                    self.modalLoading = true;
                  });
                  if (res.ok) {
                    self.isShowModal = false;
                    self.$Message.success("新增章节成功");
                    self.getChapters();
                  }
                })
                .catch((err) => {
                  self.modalLoading = false;
                  self.$nextTick(() => {
                    self.modalLoading = true;
                  });
                });
            } else if (self.isAddOrUpdateModal === "update") {
              data.bookid = this.$route.params.bookid;
              oldHttp
                .patch(
                  "/api/admin/chapter/" + self.currentChapterId,
                  data,
                  "修改章节"
                )
                .then((res) => {
                  self.modalLoading = false;
                  // 避免校验完直接关闭弹窗
                  self.$nextTick(() => {
                    self.modalLoading = true;
                  });
                  if (res.ok) {
                    self.isShowModal = false;
                    self.$Message.success("修改章节成功");
                    self.getChapters();
                  }
                })
                .catch((err) => {
                  self.modalLoading = false;
                  self.$nextTick(() => {
                    self.modalLoading = true;
                  });
                });
            }
          } else {
            self.modalLoading = false;
            self.modalError.num = Math.random().toString();
            self.$nextTick(function () {
              self.modalError.num = "请输入整数";
              self.modalLoading = true;
            });
          }
        } else {
          self.modalLoading = false;
          self.$nextTick(() => {
            self.modalLoading = true;
          });
        }
      });
    },
    handleModalCancel() {
      this.$refs["modalForm"].resetFields();
    },
    downloadChapter() {
      // let iframe = document.createElement('iframe')
      // iframe.style.display = 'none'
      // iframe.src = './download/upload_example'
      // iframe.onload = function() {
      //   document.body.removeChild(iframe)
      // }
      // document.body.appendChild(iframe)
      oldHttp
        .get(
          "/api/admin/book/" + this.$route.params.bookid + "/generate_txt",
          {},
          "下载章节"
        )
        .then((res) => {
          if (res.ok) {
            window.open(
              baseURL + "/api/download?path=" + encodeURIComponent(res.url)
            );
          } else {
            self.$Message.success("下载失败");
          }
        });
    },
    handleBeforeUpload() {
      this.$Loading.start();
    },
    handleSuccess(res) {
      this.$Loading.finish();
      if (res && res.ok) {
        this.$Modal.success({
          title: "上传成功",
          content:
            "成功导入" +
            res.success +
            "条数据<br>" +
            (res.errors.length > 0
              ? "出现如下错误: <br>" + res.errors.join("、<br>")
              : ""),
        });
        this.getChapters();
      } else {
        this.$Notice.warning({
          title: "上传出错",
          desc: res.msg ? res.msg : "出现未知错误",
        });
      }
    },
    handleFormatError(file) {
      this.$Loading.error();
      this.$Notice.warning({
        title: "上传文件格式错误",
        desc: "请下载上传模板，按照对的格式上传",
      });
    },
    handleError(res) {
      this.$Notice.warning({
        title: "上传出错",
        desc: "出现未知错误",
      });
    },
    // 点击分页
    handlePageChange(val) {
      this.page = val;
      this.getChapters();
    },
    handleSizeChange(val) {
      this.limit = val;
      this.page = 1;
      this.getChapters();
    },
    // 章节表格点击分页
    handleUploadPageChange(val) {
      this.uploadPage = val;
      this.spliceUploadArray();
    },
    // 分页展示章节信息
    spliceUploadArray() {
      this.curChapters = this.errorChapters.slice(
        (this.uploadPage - 1) * 5,
        this.uploadPage * 5
      );
    },
    closeUploadModal() {
      this.currentStep = 0;
      this.step = [
        { title: "读取本地文件", content: "读取中.." },
        { title: "解析书籍章节", content: "未开始.." },
        { title: "确认章节", content: "未开始.." },
        { title: "导出excel文件", content: "未开始.." },
      ];
      this.showUploadingModal = false;
      // 清除file input的值
      let file = document.getElementById("upload");
      file.value = "";
    },
    // 上传弹窗点击确定
    handleUploadModalConfrim() {
      if (this.currentStep === 2) {
        // 每10章10章的更新书籍
        this.step[2].content = "正在打包数据为excel文件...";
        let option = {};
        option.fileName = this.bookInfo.name;
        option.datas = [
          {
            sheetData: this.uploadChapters,
            sheetName: "",
            sheetFilter: ["num", "name", "content", "info"],
            sheetHeader: ["章节序号", "章节名称", "章节内容", "说明"],
          },
        ];
        let toExcel = new ExportJsonExcel(option); //new
        toExcel.saveExcel(); //保存
      }
    },
    // 处理文件上传
    fileHandler(event) {
      // 检查浏览器是否支持FileReader API
      if (window.File && window.FileReader && window.FileList && window.Blob) {
        let file = event.currentTarget.files[0];
        let textType = /text.*/;
        if (file.type.match(textType)) {
          let reader = new FileReader();
          reader.readAsText(event.currentTarget.files[0], "utf8");
          // 开始读取
          reader.onloadstart = () => {
            this.showUploadingModal = true;
          };
          // 读取中
          reader.onprogress = (evt) => {
            // evt is an ProgressEvent.
            if (evt.lengthComputable) {
              this.step[0].content =
                "读取进度: " + Math.round((evt.loaded / evt.total) * 100) + "%";
            }
          };
          // 读取完成
          reader.onload = (result) => {
            // 第一步完成
            this.currentStep = 1;
            this.step[0].content = "读取完成";
            console.log("----读取完成，开始分析数据----");
            // 开始分析数据
            const chapterTitleReg = /(^|\n+\s*)第?[零一二两三叁四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰0-9]+章[\.、：: -]*[^\n]+/gim;
            let matchResult = null;
            let chapters = []; // 记录已经匹配到的章节
            let count = 0; // 记录匹配到的次数
            while (
              (matchResult = chapterTitleReg.exec(reader.result)) !== null
            ) {
              if (matchResult && matchResult[0]) {
                const num = chinese2num(
                  matchResult[0]
                    .match(
                      /第?[零一二两三叁四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰0-9]+章/
                    )[0]
                    .replace(/[第章]+/g, "")
                );
                let tmpTitle = matchResult[0].replace(
                  /^\n+\s*.*章[、\.：\s:-]*/,
                  ""
                );
                if (tmpTitle) {
                  chapters.push({
                    num,
                    name: tmpTitle.trim(),
                    resultIndex: matchResult.index + matchResult[0].length,
                    lastIndex:
                      chapterTitleReg.lastIndex - matchResult[0].length,
                  });
                  count++;
                }
              }
            }

            // 遍历章节获取到章节内容
            let formatContent = (str) => {
              let result = str;
              let rules = [
                /\(\)/g, // 特殊的括号
                /^\n+/g, // 章节前换行
                /\n+$/g, // 章节后换行
                /((快来看)|(福利)|(添加)|(美女)|(关注)|(给力)|(好看)).*小说！/g, // 关注微信消息
              ];
              rules.forEach((item) => {
                result = result.replace(item, "");
              });
              return result.trim();
            };

            for (let i = 0; i < chapters.length; i++) {
              let content = "";
              if (i === chapters.length - 1) {
                content = formatContent(
                  reader.result.substring(chapters[i].resultIndex)
                );
              } else {
                content = formatContent(
                  reader.result.substring(
                    chapters[i].resultIndex,
                    chapters[i + 1].lastIndex
                  )
                );
              }
              delete chapters[i].lastIndex;
              delete chapters[i].resultIndex;
              chapters[i].content = content.replace(/[\r\n]+\s*/g, "\n  ");
            }

            // 内容为空的章节去重
            chapters = chapters.filter((item) => {
              return item.content;
            });

            console.log(chapters);

            // 章节错误检测
            let errorChapter = [];
            for (let i = 0; i < chapters.length; i++) {
              // 残章检测
              let error1 = false;
              if (chapters[i - 1]) {
                if (chapters[i].num !== chapters[i - 1].num + 1) {
                  error1 = true;
                }
              }
              // 检测特殊字符
              let error2 = false;
              let reg = /^\w+$/g;
              if (error1) {
                chapters[i].error = `章节不连贯，当前章节是第${
                  chapters[i].num
                }章，往前一章是第${chapters[i - 1].num}章`;
              }
              if (error2) {
                chapters[i].error = chapters[i].error
                  ? chapters[i].error + "，包含不能识别的特殊字符"
                  : "包含不能识别的特殊字符";
              }
              if (error1 || error2) {
                errorChapter.push(chapters[i]);
              }
            }

            // 章节分析完毕
            this.currentStep = 2;
            this.step[1].content = "分析完毕";
            this.step[2].content = "确认中...";
            // this.chapters = chapters;
            // this.spliceUploadArray();
            // 展示可能处错误的章节
            this.uploadChapters = chapters;
            this.errorChapters = errorChapter;
            this.spliceUploadArray();
          };
        } else {
          this.$Notice.warning({
            title: "上传文件格式错误",
            desc: "请上传UTF8编码格式的文本文件",
          });
        }
      } else {
        alert("当前浏览器不支持FileReader，请更换浏览器");
      }
    },
  },
  created() {
    this.getChapters();
    this.uploadUrl =
      baseURL +
      "/api/admin/book/" +
      this.$route.params.bookid +
      "/chapter_upload";
    this.uploadHeader.Authorization = Cookies.get("mbook-admin-token");
  },
};
</script>

<style lang="scss">
.book-chapter .title {
  height: 32px;
  line-height: 32px;
}

.book-chapter .add-icon {
  float: right;
  margin-left: 10px;
}

.book-chapter .upload-label {
  float: right;
  margin-left: 10px;
  line-height: 32px;
}

.book-chapter .overflow-text {
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.book-chapter .ivu-tooltip-inner {
  max-width: inherit;
}

.book-chapter .change-btn {
  margin-right: 15px;
}

.book-chapter .modal-container {
  width: 600px;
  position: absolute;
  left: 50%;
  top: 0;
  margin-left: -300px;
}

.small-font textarea {
  font-size: 12px !important;
}

.book-chapter .pager {
  text-align: right;
  margin-top: 30px;
}

.book-chapter .upload-btn {
  display: inline-block;
  float: right;
  vertical-align: middle;
  margin-left: 10px;
  height: 33px;
  margin-top: -1px;
}
</style>
